package service

import (
	"context"
	"mini-app/config/mysql"
	"mini-app/internal/app/grpc/client"
	"mini-app/internal/app/grpc/common"
	"mini-app/internal/app/grpc/protoc/sale_adminc"
	"mini-app/internal/dal"
	"mini-app/internal/dao"
	"mini-app/internal/define"
	"mini-app/internal/models"
	"time"

	"192.168.1.75/go-pkg/helper"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
	"gorm.io/gorm"
)

type OnlineEvent struct{}

type OnlineEventListT struct {
	ID                string `json:"id"`                  // 活动id
	Name              string `json:"name"`                // 活动名称
	Image             string `json:"image"`               // 活动图片
	StartTime         int64  `json:"start_time"`          // 开始时间
	EndTime           int64  `json:"end_time"`            // 结束时间
	LimitedFree       int64  `json:"limited_free"`        // 限免数量
	JoinedUser        int64  `json:"joined_user"`         // 已申请人数
	OnlineEventStatus int    `json:"online_event_status"` // 活动状态
	RequirePoints     int64  `json:"require_points"`      // 参与积分
	GoodsID           string `json:"goods_id"`            // 商品id
	GoodsName         string `json:"goods_name"`          // 商品名称
	GoodsImage        string `json:"goods_image"`         // 商品图片
	SupportID         string `json:"support_id"`
	CheckGenderType   int    `json:"check_gender_type"` // 校验性别类型
}

// List 活动列表
// 活动信息-活动图片、活动时间、限免数量、已申请人数，活动状态，参与积分
func (OnlineEvent) List(ctx context.Context, openID, name string, status int, page, limit int) ([]OnlineEventListT, int64) {
	var list []OnlineEventListT
	records, total := dao.OnlineEvent{}.List(ctx, mysql.NewDB(), name, status, define.State_Yes, define.State_No,
		page, limit)
	for _, record := range records {
		if record.Status == 0 {
			if record.StartTime <= time.Now().Unix() && record.EndTime >= time.Now().Unix() {
				record.Status = 1 // 进行中
			} else if record.StartTime > time.Now().Unix() {
				record.Status = 2 // 未开始
			} else if record.EndTime < time.Now().Unix() {
				record.Status = 3 // 已结束
			}
		}
		// 获取supportID
		var supportID string
		if openID != "" {
			onlineEventUserDetail := dao.OnlineEventUser{}.Detail(ctx, mysql.NewDB(), "", openID, record.ID)
			if onlineEventUserDetail != nil {
				supportID = onlineEventUserDetail.ID
			}
		}
		// 获取商品信息
		var goodsName, goodsImage string
		rsp := common.GRPC{}.GoodsDetail(ctx, record.GoodsID)
		if rsp != nil {
			goodsName = rsp.GoodsName
			goodsImage = rsp.GoodsImage
		}
		totalUser := dao.OnlineEventUser{}.Count(ctx, mysql.NewDB(), record.ID, 0)
		list = append(list, OnlineEventListT{
			ID:                record.ID,
			Name:              record.Name,
			Image:             record.Image,
			StartTime:         record.StartTime,
			EndTime:           record.EndTime,
			LimitedFree:       record.LimitedFree,
			JoinedUser:        totalUser + record.BaseJoinedUser,
			OnlineEventStatus: record.Status,
			RequirePoints:     record.RequirePoints,
			GoodsID:           record.GoodsID,
			CheckGenderType:   record.CheckGenderType,
			GoodsName:         goodsName,
			GoodsImage:        goodsImage,
			SupportID:         supportID,
		})
	}
	return list, total
}

type OnlineEventDetailT struct {
	Name              string  `json:"name"`               // 活动名称
	Image             string  `json:"image"`              // 活动图片
	StartTime         int64   `json:"start_time"`         // 开始时间
	EndTime           int64   `json:"end_time"`           // 结束时间
	LimitedFree       int64   `json:"limited_free"`       // 限免数量
	JoinedUser        int64   `json:"joined_user"`        // 已申请人数
	Status            int64   `json:"status"`             // 活动状态
	RequirePoints     int64   `json:"require_points"`     // 参与积分
	CurrentPoints     int64   `json:"current_points"`     // 当前积分
	RequireSupporters int     `json:"require_supporters"` // 需要助力的人数
	CurrentSupporters int     `json:"current_supporters"` // 已助力的人数
	GoodsID           string  `json:"goods_id"`           // 商品id
	GoodsName         string  `json:"goods_name"`         // 商品名称
	GoodsPrice        float64 `json:"goods_price"`        // 商品价格
	GoodsImage        string  `json:"goods_image"`        // 商品图片
	SupportID         string  `json:"support_id"`         // 助力id
	PurchaseMethod    int     `json:"purchase_method"`    // 购买方式
	GoodsLink         string  `json:"goods_link"`         // 第三方商品链接
	CheckGenderType   int     `json:"check_gender_type"`  // 校验性别类型
}

// Detail 活动详情
// 活动信息-活动图片，活动时间，限免数量，已申请人数，活动状态，参与积分
// 商品信息-商品主图，商品价格
// 助力信息-助力ID
func (OnlineEvent) Detail(ctx context.Context, openid, onlineEventID string) (*OnlineEventDetailT, error) {
	var detail OnlineEventDetailT
	onlineEventDetail := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), onlineEventID)
	if onlineEventDetail == nil {
		return nil, errorx.New("活动不存在", -1)
	}
	detail.Name = onlineEventDetail.Name
	detail.Image = onlineEventDetail.Image
	detail.StartTime = onlineEventDetail.StartTime
	detail.EndTime = onlineEventDetail.EndTime
	detail.LimitedFree = onlineEventDetail.LimitedFree
	detail.RequirePoints = onlineEventDetail.RequirePoints
	detail.PurchaseMethod = onlineEventDetail.PurchaseMethod
	detail.GoodsLink = onlineEventDetail.GoodsLink
	detail.CheckGenderType = onlineEventDetail.CheckGenderType
	// 活动状态
	if detail.Status == 0 {
		if detail.StartTime <= time.Now().Unix() && detail.EndTime >= time.Now().Unix() {
			detail.Status = 1 // 进行中
		} else if detail.StartTime > time.Now().Unix() {
			detail.Status = 2 // 未开始
		} else if detail.EndTime < time.Now().Unix() {
			detail.Status = 3 // 已结束
		}
	}
	detail.JoinedUser = dao.OnlineEventUser{}.Count(ctx, mysql.NewDB(), onlineEventDetail.ID, 0) + onlineEventDetail.BaseJoinedUser
	// 获取当前积分
	userInfo, _ := dao.User{}.UserInfo(ctx, dal.Q, openid, "", "")
	if userInfo != nil {
		detail.CurrentPoints = userInfo.Points
	}
	// 获取商品信息
	rsp := common.GRPC{}.GoodsDetail(ctx, onlineEventDetail.GoodsID)
	if rsp != nil {
		detail.GoodsID = rsp.GoodsId
		detail.GoodsName = rsp.GoodsName
		detail.GoodsImage = rsp.GoodsImage
		detail.GoodsPrice = rsp.GoodsPrice
	}
	// 获取助力id，为空时，表示用户还未申请成功
	eventUserDetail := dao.OnlineEventUser{}.Detail(ctx, mysql.NewDB(), "", openid, onlineEventID)
	if eventUserDetail != nil {
		detail.SupportID = eventUserDetail.ID
		detail.RequireSupporters = int(onlineEventDetail.RequireSupporters)
		detail.CurrentSupporters = eventUserDetail.CurrentSupporters
	}
	return &detail, nil
}

// Join 参加活动
func (OnlineEvent) Join(ctx context.Context, openID string, onlineEventID string, userAddress models.UserAddress) error {
	// 收货地址检查
	if userAddress.UserName == "" {
		return errorx.New("收货人姓名不能为空", -1)
	}
	if userAddress.TelNumber == "" {
		return errorx.New("收货人手机号不能为空", -1)
	}
	if userAddress.ProvinceName == "" {
		return errorx.New("收货省份不能为空", -1)
	}
	if userAddress.CityName == "" {
		return errorx.New("收货城市不能为空", -1)
	}
	if userAddress.DetailAddress == "" {
		return errorx.New("收货详细地址不能空", -1)
	}
	// 获取活动详情
	onlineEventDetail := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), onlineEventID)
	if onlineEventDetail == nil {
		return errorx.New("活动不存在", -1)
	}
	if onlineEventDetail.EndTime < time.Now().Unix() {
		return errorx.New("活动已结束", -1)
	}
	if onlineEventDetail.StartTime > time.Now().Unix() {
		return errorx.New("活动未开始", -1)
	}
	// 获取用户详情
	userDetail, _ := dao.User{}.UserInfo(ctx, dal.Q, openID, "", "")
	if userDetail == nil {
		return errorx.New("用户不存在", -1)
	}
	// 判断积分是否满足 参与活动先冻结积分
	if userDetail.Points < onlineEventDetail.RequirePoints {
		return errorx.New("积分不足", -1)
	}
	db := mysql.NewDB()
	err := db.Transaction(func(tx *gorm.DB) error {
		// 0积分不进行积分扣除检查
		if onlineEventDetail.RequirePoints > 0 {
			// 扣减积分
			err := dao.User{}.SubPoints(ctx, dal.Use(tx), openID, onlineEventDetail.RequirePoints)
			if err != nil {
				return errorx.New("积分不足", -1)
			}
		}
		// 创建订单
		// 获取商品信息
		saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
		if saleAdminClientErr != nil {
			logx.Error(ctx, "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
			return errorx.New("获取商品信息失败", -1)
		}
		rsp, err := saleAdminClient.GoodsDetail(ctx, &sale_adminc.GoodsDetailReq{GoodsId: onlineEventDetail.GoodsID})
		if err != nil {
			return errorx.New("获取商品信息失败", -1)
		}
		if rsp.GoodsId == "" {
			return errorx.New("商品不存在", -1)
		}
		// 获取运费
		expressFeeRsp, err := saleAdminClient.ExpressFee(
			ctx,
			&sale_adminc.ExpressFeeReq{
				GoodsId:  onlineEventDetail.GoodsID,
				Province: userAddress.ProvinceName,
			},
		)
		if err != nil {
			return errorx.New("获取运费信息失败", -1)
		}
		if expressFeeRsp.Msg != "" {
			return errorx.New(expressFeeRsp.Msg, -1)
		}
		onlineEventUserDetail := dao.OnlineEventUser{}.Detail(ctx, tx, "", openID, onlineEventID)
		if onlineEventUserDetail != nil {
			return errorx.New("不能重复申请", -1)
		}
		// 创建订单（订单状态： 活动申请待揭晓）
		outTradeNo, err := dao.Order{}.Create(
			ctx,
			dal.Use(tx),
			openID,
			"",                                // 可自动生成
			"",                                // 可自动生成
			"",                                // 活动订单不关联设备
			define.OrderStatusApplyingPending, // 已申请，待公布结果
			onlineEventDetail.GoodsID,         // 商品id
			int(rsp.GoodsType),                // 商品类型
			rsp.GoodsName,                     // 商品名称
			1, 0.00, 0.00, 0, expressFeeRsp.Fee, 2,
			onlineEventID,
			userAddress,
		)
		if err != nil {
			return errorx.New("创建订单失败", -1)
		}
		// 新增参与用户
		success := dao.OnlineEventUser{}.Create(
			ctx,
			tx,
			onlineEventID,
			userDetail.ID,
			userDetail.OpenID,
			0,
			onlineEventDetail.RequirePoints,
			userAddress,
			outTradeNo,
		)
		if !success {
			return errorx.New("不能重复申请", -1)
		}
		// 在线活动增加参与人数
		dao.OnlineEvent{}.AddJoinedUser(ctx, tx, onlineEventID)
		return nil
	})
	return err
}

type SupporterT struct {
	NickName string `json:"nick_name"` // 昵称
	Image    string `json:"image"`     // 头像
}
type SupportDetailT struct {
	SupportID         string       `json:"support_id"`         // 助力ID
	UserID            string       `json:"user_id"`            // 用户id
	WechatName        string       `json:"wechat_name"`        // 用户昵称
	WechatAvatar      string       `json:"wechat_avatar"`      // 用户头像
	LimitedFree       int64        `json:"limited_free"`       // 限免数量
	StartTime         int64        `json:"start_time"`         // 开始时间
	EndTime           int64        `json:"end_time"`           // 结束时间
	GoodsName         string       `json:"goods_name"`         // 商品名称
	GoodsImage        string       `json:"goods_image"`        // 商品图
	JoinedUser        int64        `json:"joined_user"`        // 已申请人数
	Supporters        []SupporterT `json:"supporters"`         // 助力成员
	RequireSupporters int          `json:"require_supporters"` // 需要助力的人数
	CurrentSupporters int          `json:"current_supporters"` // 已助力的人数
	CheckGenderType   int          `json:"check_gender_type"`
}

// SupportDetail 助力详情
// 活动信息-活动时间，限免数量，已申请
// 商品信息-商品名称
// 已助力好友
func (OnlineEvent) SupportDetail(ctx context.Context, supportID string) (*SupportDetailT, error) {
	var supportDetail SupportDetailT
	// 参数用户详情
	if supportID == "" {
		return nil, errorx.New("参数记录为空", -1)
	}
	onlineEventUserDetail := dao.OnlineEventUser{}.Detail(ctx, mysql.NewDB(), supportID, "", "")
	if onlineEventUserDetail == nil {
		return nil, errorx.New("参与记录为空", -1)
	}
	supportDetail.SupportID = onlineEventUserDetail.ID
	// 用户信息
	userInfo, _ := dao.User{}.UserInfo(ctx, dal.Q, onlineEventUserDetail.OpenID, "", "")
	if userInfo != nil {
		supportDetail.UserID = userInfo.ID
		supportDetail.WechatName = userInfo.NickName
		supportDetail.WechatAvatar = userInfo.Image
	}
	// 活动信息
	eventDetail := dao.OnlineEvent{}.Detail(ctx, mysql.NewDB(), onlineEventUserDetail.OnlineEventID)
	if eventDetail != nil {
		supportDetail.LimitedFree = eventDetail.LimitedFree
		supportDetail.StartTime = eventDetail.StartTime
		supportDetail.EndTime = eventDetail.EndTime
		supportDetail.CheckGenderType = eventDetail.CheckGenderType
		// 获取商品信息
		rsp := common.GRPC{}.GoodsDetail(ctx, eventDetail.GoodsID)
		if rsp != nil {
			supportDetail.GoodsName = rsp.GoodsName
			supportDetail.GoodsImage = rsp.GoodsImage
		}
	}
	// 已申请人数
	supportDetail.JoinedUser = dao.OnlineEventUser{}.Count(ctx, mysql.NewDB(), onlineEventUserDetail.OnlineEventID, 0) + eventDetail.BaseJoinedUser
	// 助力用户信息-名字/头像
	supporterList := dao.OnlineEventSupportLog{}.List(ctx, mysql.NewDB(), "", supportID)
	for _, supporter := range supporterList {
		var supporterInfo SupporterT
		userInfo, _ := dao.User{}.UserInfo(ctx, dal.Q, supporter.OpenID, "", "")
		if userInfo != nil {
			supporterInfo.NickName = userInfo.NickName
			supporterInfo.Image = userInfo.Image
			supportDetail.Supporters = append(supportDetail.Supporters, supporterInfo)
		}
	}
	supportDetail.RequireSupporters = int(eventDetail.RequireSupporters)
	supportDetail.CurrentSupporters = onlineEventUserDetail.CurrentSupporters
	if len(supportDetail.Supporters) == 0 {
		supportDetail.Supporters = []SupporterT{}
	}
	return &supportDetail, nil
}

// Support 助力
func (OnlineEvent) Support(ctx context.Context, openid, supportID string) error {
	joinDetail := dao.OnlineEventUser{}.Detail(ctx, mysql.NewDB(), supportID, "", "")
	if joinDetail == nil {
		return errorx.New("活动不存在", -1)
	}
	if openid == joinDetail.OpenID {
		return errorx.New("不允许给自己助力", -1)
	}
	success := dao.OnlineEventSupportLog{}.Create(ctx, mysql.NewDB(), openid, supportID)
	if success {
		dao.OnlineEventUser{}.AddSupports(ctx, mysql.NewDB(), supportID)
	} else {
		return errorx.New("重复助力", -1)
	}
	onlineEventUserDetail := dao.OnlineEventUser{}.Detail(ctx, mysql.NewDB(), supportID, "", "")
	// 助力成功，更新申请状态
	if onlineEventUserDetail.CurrentSupporters >= onlineEventUserDetail.RequireSupporters && joinDetail.Status == 0 {
		dao.OnlineEventUser{}.SetApplySuccess(ctx, mysql.NewDB(), supportID)
	}
	return nil
}

type WinnerListT struct {
	UserID       string `json:"user_id"`       // 用户id
	WechatName   string `json:"wechat_name"`   // 微信昵称
	WechatAvatar string `json:"wechat_avatar"` // 微信头像
}

func (OnlineEvent) WinnerList(
	ctx context.Context,
	onlineEventID string,
	page, limit int,
) (list []WinnerListT, total int64) {
	records, total, err := dao.OnlineEventUser{}.List(ctx, mysql.NewDB(),
		onlineEventID, 2, nil, nil, nil, nil, page, limit)
	if err != nil {
		logx.Error(ctx, "get online event user list error", logx.Any("err", err))
		return nil, 0
	}

	for _, record := range records {
		image := ""
		name := ""
		if record.IsPuppetUser == false {
			userDetail, _ := dao.User{}.UserInfo(ctx, dal.Q, record.OpenID, "", "")
			if userDetail != nil {
				image = userDetail.Image
				name = userDetail.NickName
			}

		} else {
			uid, err := helper.StringToInt64(record.UserID)
			if err != nil {
				logx.Error(ctx, "parse user id error", logx.Any("err", err))
				continue
			}
			userDetail, _ := dao.NewPuppetUserRepo(ctx).FindOneById(ctx, uid)
			if userDetail != nil {
				image = userDetail.Avatar
				name = userDetail.NickName
			} else {
				logx.Error(ctx, "puppet user not found", logx.Any("uid", uid))
			}
		}

		list = append(list, WinnerListT{
			UserID:       record.UserID,
			WechatName:   name,
			WechatAvatar: image,
		})
	}
	if len(list) == 0 {
		list = []WinnerListT{}
	}
	return
}
